﻿#region imports

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Codeplex.ODataTFS.Model.Entities;
using Codeplex.ODataTFS.Model.ExpressionVisitors;
using Codeplex.ODataTFS.Model.Serialization;
using Microsoft.Data.Services.Toolkit.QueryModel;

#endregion

namespace Codeplex.ODataTFS.Model.Repositories
{
	public class ChangesetRepository
	{
		private readonly TFSChangesetProxy _proxy;

		public ChangesetRepository(TFSChangesetProxy proxy)
		{
			_proxy = proxy;
		}

		public Changeset GetOne(string id)
		{
			var changesetId = 0;
			if (!int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out changesetId))
			{
				throw new ArgumentException("The parameter id should be numeric", "id");
			}

			return _proxy.GetChangeset(changesetId);
		}

		[RepositoryBehavior(HandlesFilter = true)]
		public IEnumerable<Changeset> GetChangesetsByProject(ODataSelectManyQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var parameters = new ChangesetFilterExpressionVisitor(operation.FilterExpression).Eval();
			int topRequestValue = GetTopRequestValue(operation, parameters);

			return _proxy.GetChangesetsByProject(operation.Key, parameters, topRequestValue);
		}

		[RepositoryBehavior(HandlesFilter = true)]
		public IEnumerable<Changeset> GetChangesetsByBranch(ODataSelectManyQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var parameters = new ChangesetFilterExpressionVisitor(operation.FilterExpression).Eval();
			int topRequestValue = GetTopRequestValue(operation, parameters);

			return _proxy.GetChangesetsByBranch(operation.Key, parameters, topRequestValue);
		}

		public IEnumerable<Changeset> GetChangesetsByBuild(string project, string definition, string number)
		{
			return _proxy.GetChangesetsByBuild(project, definition, number);
		}

		[RepositoryBehavior(HandlesFilter = true)]
		public IEnumerable<Changeset> GetAll(ODataQueryOperation operation)
		{
			if (operation == null)
			{
				throw new ArgumentNullException("operation");
			}

			var parameters = new ChangesetFilterExpressionVisitor(operation.FilterExpression).Eval();
			int topRequestValue = GetTopRequestValue(operation, parameters);

			return _proxy.GetChangesetsByProjectCollection(parameters, topRequestValue);
		}

		/// <summary>
		///     Gets the count treshold to minimize the number of elements retrieved from TFS
		/// </summary>
		private int GetTopRequestValue(ODataQueryOperation operation, FilterNode parameters)
		{
			int topRequestValue = int.MaxValue;

			if (parameters == null || !parameters.Any(p => p.Key.Equals("Owner") || p.Key.Equals("CreationDate") || p.Key.Equals("Comment") || p.Key.Equals("ArtifactUri")))
			{
				if (operation.IsCountRequest)
				{
					if (!string.IsNullOrEmpty(operation.ContinuationToken))
					{
						var parts = operation.ContinuationToken.Split(':').Select(int.Parse);
						topRequestValue = parts.First() + parts.Last() + 1;
					}
				}
				else
				{
					if (operation.TopCount > 0)
					{
						topRequestValue = operation.TopCount + operation.SkipCount + 1;
					}
				}
			}

			return topRequestValue;
		}
	}
}
